(ns
  com.marzhillstudios.molehill.vcs
  (:use [clojure.contrib.shell-out :only [sh]]
     [clojure.contrib.logging])
  (:require [clojure.contrib [str-utils2 :as s]]))

; private api
(defn clean-lines
  [& lines]
  (map #(s/drop % 2) lines))

(defn run-hg-command
  [& args]
  (debug (str "running hg command" args))
  (apply sh "hg" args))

(defn run-status-command
  [& args]
  (s/split-lines (apply run-hg-command "status" args)))

;public api
(defn new-files
  []
  (apply clean-lines (run-status-command "-u")))

(defn modified-files
  []
  (apply clean-lines (run-status-command "-u" "-a")))

(defn changed-files
  []
  {:new (new-files) :modified (modified-files)})

(defn commit
  ([msg]
    (run-hg-command "commit" "-m" msg))
  ([file msg]
    (run-hg-command "commit" "-m" msg file)))

(defn add
  [file]
  (run-hg-command "add" file))

(defn rm
  [file]
  (run-hg-command "rm" file))

(defn init
  []
  (run-hg-command "init"))

(defn find-files [pattern]
  (debug (str "finding files matching pattern: " pattern))
  (s/split-lines (run-hg-command "locate" pattern)))

(defn all-tracked
  []
  (s/split-lines (run-hg-command "manifest")))

(defn tracked?
  {:tag Boolean}
  [file]
  (= (find-files file)
     file))

(defmacro with-commit
  "Do code with a vcs commit afterward"
  [msg & body]
  `(do
     ~@body
     (commit ~msg)))
